package com.quectel.util.common;

import com.quectel.util.ex.common.EncodeException;
import com.quectel.util.ex.common.ServletException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * servlet帮助类
 *
 * @author caolu
 * @email louis.cao@quectel.com
 */
@Slf4j
public class ServletUtils {

    /**
     * 向客户端写入文件
     *
     * @param response
     * @param file
     * @param fileName 为空取file.getName()
     */
    public static void write(HttpServletResponse response, File file, String fileName) {
        response.addHeader("Content-Length", "" + file.length());
        response.setContentType("application/octet-stream");

        String downloadName = fileName == null ? file.getName() : fileName;
        String headerValue = "attachment;";
        headerValue += " filename=\"" + encodeURIComponent(downloadName) + "\";";
        headerValue += " filename*=utf-8''" + encodeURIComponent(downloadName);
        response.setHeader("Content-Disposition", headerValue);

        try (FileInputStream fis = new FileInputStream(file)) {
            IOUtils.copyLarge(fis, response.getOutputStream());
        } catch (Exception e) {
            throw new ServletException("Servlet output stream write error", e);
        }
    }

    /**
     * 向客户端写入文件
     *
     * @param response
     * @param in
     * @param fileName 为空取file.getName()
     */
    public static void write(HttpServletResponse response, InputStream in, String fileName) {
//        try {
//            response.addHeader("Content-Length", "" + in.available());
//        } catch (IOException e) {
//            log.error("Set Content-Length header error");
//        }

        response.setContentType("application/octet-stream");

        String headerValue = "attachment;";
        headerValue += " filename=\"" + encodeURIComponent(fileName) + "\";";
        headerValue += " filename*=utf-8''" + encodeURIComponent(fileName);
        response.setHeader("Content-Disposition", headerValue);

        try (InputStream is = in) {
            IOUtils.copyLarge(is, response.getOutputStream());
        } catch (Exception e) {
            throw new ServletException("Servlet output stream write error", e);
        }
    }


    /**
     * 向客户端写入文件
     *
     * @param response
     * @param in
     * @param fileName 为空取file.getName()
     * @param fileType jpg svg png
     */
    public static void writeImg(HttpServletResponse response, InputStream in, String fileName, String fileType) {
        try {
            response.addHeader("Content-Length", "" + in.available());
        } catch (IOException e) {
            log.error("Set Content-Length header error");
        }

        if ("svg".equalsIgnoreCase(fileType)) {
            response.setContentType("image/svg+xml");
        } else {
            response.setContentType("image/" + fileType);
        }

        String headerValue = "attachment;";
        headerValue += " filename=\"" + encodeURIComponent(fileName) + "\";";
        headerValue += " filename*=utf-8''" + encodeURIComponent(fileName);
        response.setHeader("Content-Disposition", headerValue);

        try (InputStream is = in) {
            IOUtils.copyLarge(is, response.getOutputStream());
        } catch (Exception e) {
            throw new ServletException("Servlet output stream write error", e);
        }
    }


    /**
     * <pre>
     * 符合 RFC 3986 标准的“百分号URL编码”
     * 在这个方法里，空格会被编码成%20，而不是+
     * 和浏览器的encodeURIComponent行为一致
     * </pre>
     *
     * @param value
     * @return
     */
    private static String encodeURIComponent(String value) {
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new EncodeException("Encode uri error", e);
        }
    }

}
